package book

import (
	"context"
	"time"

	"BookStack/internal/domain/events"
	appErrors "BookStack/pkg/errors"
	"BookStack/pkg/utils"
)

// 创建书籍
func (s *service) CreateBook(ctx context.Context, req *CreateBookRequest) (*BookResponse, error) {
	// 调用领域服务创建书籍
	book, err := s.bookService.CreateBook(
		ctx,
		req.Title,
		req.Description,
		req.Cover,
		req.Slug,
		"", // 默认ISBN为空
		"", // 默认Author为空
		0,  // 默认CategoryID为0
		req.CreatedBy,
	)

	// 处理错误
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok {
			switch appErr.Code {
			case appErrors.ErrCodeBookTitleRequired:
				return nil, BookTitleRequired()
			case appErrors.ErrCodeBookSlugExists:
				return nil, BookSlugExists(req.Slug)
			default:
				return nil, DatabaseError(err)
			}
		}
		return nil, DatabaseError(err)
	}

	// 发布书籍创建事件
	event := &events.BookCreatedEvent{
		ID:          book.ID,
		Title:       book.Title,
		Slug:        book.Slug,
		Description: book.Description,
		Cover:       book.Cover,
		Status:      book.Status,
		CreatedBy:   book.CreatedBy,
		CreatedAt:   utils.TimeToJSONTime(book.CreatedAt),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookCreatedEventType, event))

	// 转换为响应DTO
	return BookToResponse(book), nil
}

// 通过ID获取书籍
func (s *service) GetBookByID(ctx context.Context, id uint) (*BookResponse, error) {
	// 调用领域服务获取书籍
	book, err := s.bookService.GetBookByID(ctx, id)

	// 处理错误
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return nil, BookNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	return BookToResponse(book), nil
}

// 通过Slug获取书籍
func (s *service) GetBookBySlug(ctx context.Context, slug string) (*BookResponse, error) {
	// 调用领域服务获取书籍
	book, err := s.bookService.GetBookBySlug(ctx, slug)

	// 处理错误
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return nil, BookNotFound(0) // ID为0表示通过slug查询
		}
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	return BookToResponse(book), nil
}

// 更新书籍
func (s *service) UpdateBook(ctx context.Context, id uint, req *UpdateBookRequest, updatedBy uint) (*BookResponse, error) {
	// 检查书籍是否存在
	_, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return nil, BookNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 调用领域服务更新书籍 - 按照正确的参数顺序
	// 参数顺序: id, title, author, description, cover, isbn, categoryID, updatedBy
	book, err := s.bookService.UpdateBook(
		ctx,
		id,
		req.Title,
		"", // Author为空字符串
		req.Description,
		req.Cover,
		"", // ISBN为空字符串
		0,  // CategoryID为0，表示不更新分类
		updatedBy,
	)

	// 处理错误
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok {
			switch appErr.Code {
			case appErrors.ErrCodeBookNotFound:
				return nil, BookNotFound(id)
			case appErrors.ErrCodeBookTitleRequired:
				return nil, BookTitleRequired()
			case appErrors.ErrCodeBookSlugExists:
				return nil, BookSlugExists(req.Slug)
			default:
				return nil, DatabaseError(err)
			}
		}
		return nil, DatabaseError(err)
	}

	// 发布书籍更新事件
	event := &events.BookUpdatedEvent{
		ID:          book.ID,
		Title:       book.Title,
		Description: book.Description,
		Cover:       book.Cover,
		Status:      book.Status,
		UpdatedBy:   updatedBy,
		UpdatedAt:   utils.TimeToJSONTime(book.UpdatedAt),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookUpdatedEventType, event))

	// 转换为响应DTO
	return BookToResponse(book), nil
}

// 删除书籍（移入回收站）
func (s *service) DeleteBook(ctx context.Context, id uint, deletedBy uint) error {
	// 首先获取书籍信息，用于事件发布
	book, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return BookNotFound(id)
		}
		return DatabaseError(err)
	}

	// 调用领域服务删除书籍
	err = s.bookService.DeleteBook(ctx, id, deletedBy)
	if err != nil {
		return DatabaseError(err)
	}

	// 发布书籍删除事件
	event := &events.BookDeletedEvent{
		ID:        book.ID,
		Title:     book.Title,
		DeletedBy: deletedBy,
		DeletedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookDeletedEventType, event))

	return nil
}

// ListBooks 获取书籍列表
func (s *service) ListBooks(ctx context.Context, params *BookQueryParams) (*BookListResponse, error) {
	// 默认分页参数
	page := 1
	pageSize := 20

	if params != nil {
		if params.Page > 0 {
			page = params.Page
		}
		if params.PageSize > 0 && params.PageSize <= 100 {
			pageSize = params.PageSize
		}
	}

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 构建过滤条件
	filters := make(map[string]interface{})
	if params != nil {
		if params.Status != nil {
			filters["status"] = *params.Status
		}
		if params.Recommend != nil {
			filters["is_recommend"] = *params.Recommend
		}
	}

	// 调用领域服务获取书籍列表
	books, total, err := s.bookService.ListBooks(ctx, offset, pageSize, filters)

	// 处理错误
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	bookResponses := make([]*BookResponse, 0, len(books))
	for _, book := range books {
		bookResponses = append(bookResponses, BookToResponse(book))
	}

	return &BookListResponse{
		Total: total,
		Items: bookResponses,
	}, nil
}

// PublishBook 发布书籍
func (s *service) PublishBook(ctx context.Context, id uint, updatedBy uint) (*BookResponse, error) {
	// 首先获取书籍信息，检查是否存在
	_, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return nil, BookNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 调用领域服务设置书籍状态为已发布
	book, err := s.bookService.SetBookStatus(ctx, id, 1, updatedBy) // 1表示已发布状态
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 发布书籍发布事件
	event := &events.BookPublishedEvent{
		ID:          book.ID,
		Title:       book.Title,
		Description: book.Description,
		Cover:       book.Cover,
		PublishedBy: updatedBy,
		PublishedAt: utils.TimeToJSONTime(book.UpdatedAt),
	}

	// 异步发布事件
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(events.BookPublishedEventType, event))

	// 转换为响应DTO
	return BookToResponse(book), nil
}

// SearchBooks 搜索书籍
func (s *service) SearchBooks(ctx context.Context, keyword string, page, pageSize int) (*BookListResponse, error) {
	// 默认分页参数
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 调用领域服务搜索书籍
	books, total, err := s.bookService.SearchBooks(ctx, keyword, offset, pageSize)

	// 处理错误
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	bookResponses := make([]*BookResponse, 0, len(books))
	for _, book := range books {
		bookResponses = append(bookResponses, BookToResponse(book))
	}

	return &BookListResponse{
		Total: total,
		Items: bookResponses,
	}, nil
}

// ToggleBookRecommend 切换书籍推荐状态
func (s *service) ToggleBookRecommend(ctx context.Context, id uint, isRecommend bool, updatedBy uint) (*BookResponse, error) {
	// 检查书籍是否存在
	_, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return nil, BookNotFound(id)
		}
		return nil, DatabaseError(err)
	}

	// 将bool类型转换为int值
	recommendValue := 0
	if isRecommend {
		recommendValue = 1
	}

	// 使用领域服务更新推荐状态
	updatedBook, err := s.bookService.SetBookRecommended(ctx, id, recommendValue, updatedBy)
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 发布书籍推荐状态变更事件
	event := &events.BookRecommendStatusChangedEvent{
		ID:            updatedBook.ID,
		Title:         updatedBook.Title,
		IsRecommend:   isRecommend,
		RecommendedBy: updatedBy,
		UpdatedAt:     utils.TimeToJSONTime(updatedBook.UpdatedAt),
	}

	// 异步发布事件
	eventType := events.BookRecommendedEventType
	if !isRecommend {
		eventType = events.BookUnrecommendedEventType
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(eventType, event))

	// 转换为响应DTO
	return BookToResponse(updatedBook), nil
}

// ListUserBooks 获取用户创建的书籍列表
func (s *service) ListUserBooks(ctx context.Context, userID uint, page, pageSize int) (*BookListResponse, error) {
	// 默认分页参数
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 调用领域服务获取用户创建的书籍列表
	filters := map[string]interface{}{
		"created_by": userID,
	}
	books, total, err := s.bookService.ListBooks(ctx, offset, pageSize, filters)

	// 处理错误
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	bookResponses := make([]*BookResponse, 0, len(books))
	for _, book := range books {
		bookResponses = append(bookResponses, BookToResponse(book))
	}

	return &BookListResponse{
		Total: total,
		Items: bookResponses,
	}, nil
}

// IncrementBookView 增加书籍浏览量
func (s *service) IncrementBookView(ctx context.Context, id uint) error {
	// 检查书籍是否存在
	_, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return BookNotFound(id)
		}
		return DatabaseError(err)
	}

	// 暂时返回nil，领域层应该实现真正的增加浏览量方法
	return nil
}

// IncrementChapterView 增加章节浏览量
func (s *service) IncrementChapterView(ctx context.Context, id uint) error {
	// 检查章节是否存在
	chapter, err := s.bookService.GetChapterByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeChapterNotFound {
			return ChapterNotFound(id)
		}
		return DatabaseError(err)
	}

	// 暂时返回nil，领域层应该实现真正的增加浏览量方法

	// 同时增加书籍的阅读次数
	err = s.IncrementBookView(ctx, chapter.BookID)
	if err != nil {
		return DatabaseError(err)
	}

	return nil
}

// ToggleBookLike 点赞/取消点赞书籍
func (s *service) ToggleBookLike(ctx context.Context, id uint, userID uint) error {
	// 检查书籍是否存在
	book, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return BookNotFound(id)
		}
		return DatabaseError(err)
	}

	// 检查用户是否已点赞
	isLiked, err := s.IsUserLikedBook(ctx, id, userID)
	if err != nil {
		return err
	}

	// 暂时不做实际操作，领域层应该实现真正的点赞/取消点赞方法

	// 发布点赞/取消点赞事件
	event := &events.BookLikeStatusChangedEvent{
		ID:        book.ID,
		Title:     book.Title,
		UserID:    userID,
		IsLiked:   !isLiked,
		CreatedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	var eventType string
	if isLiked {
		eventType = events.BookUnlikedEventType
	} else {
		eventType = events.BookLikedEventType
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(eventType, event))

	return nil
}

// ToggleBookStar 收藏/取消收藏书籍
func (s *service) ToggleBookStar(ctx context.Context, id uint, userID uint) error {
	// 检查书籍是否存在
	book, err := s.bookService.GetBookByID(ctx, id)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return BookNotFound(id)
		}
		return DatabaseError(err)
	}

	// 检查用户是否已收藏
	isStarred, err := s.IsUserStarredBook(ctx, id, userID)
	if err != nil {
		return err
	}

	// 暂时不做实际操作，领域层应该实现真正的收藏/取消收藏方法

	// 发布收藏/取消收藏事件
	event := &events.BookStarStatusChangedEvent{
		ID:        book.ID,
		Title:     book.Title,
		UserID:    userID,
		IsStarred: !isStarred,
		CreatedAt: utils.TimeToJSONTime(time.Now()),
	}

	// 异步发布事件
	var eventType string
	if isStarred {
		eventType = events.BookUnstarredEventType
	} else {
		eventType = events.BookStarredEventType
	}
	s.eventPublisher.AsyncPublish(ctx, events.NewEvent(eventType, event))

	return nil
}

// ListUserStarredBooks 获取用户收藏的书籍列表
func (s *service) ListUserStarredBooks(ctx context.Context, userID uint, page, pageSize int) (*BookListResponse, error) {
	// 默认分页参数
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 调用领域服务获取用户收藏的书籍列表
	filters := map[string]interface{}{
		"user_starred": userID,
	}
	books, total, err := s.bookService.ListBooks(ctx, offset, pageSize, filters)

	// 处理错误
	if err != nil {
		return nil, DatabaseError(err)
	}

	// 转换为响应DTO
	bookResponses := make([]*BookResponse, 0, len(books))
	for _, book := range books {
		bookResponses = append(bookResponses, BookToResponse(book))
	}

	return &BookListResponse{
		Total: total,
		Items: bookResponses,
	}, nil
}

// IsUserLikedBook 检查用户是否已点赞书籍
func (s *service) IsUserLikedBook(ctx context.Context, bookID, userID uint) (bool, error) {
	// 检查书籍是否存在
	_, err := s.bookService.GetBookByID(ctx, bookID)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return false, BookNotFound(bookID)
		}
		return false, DatabaseError(err)
	}

	// 暂时返回false，领域层应该实现真正的检查方法
	return false, nil
}

// IsUserStarredBook 检查用户是否已收藏书籍
func (s *service) IsUserStarredBook(ctx context.Context, bookID, userID uint) (bool, error) {
	// 检查书籍是否存在
	_, err := s.bookService.GetBookByID(ctx, bookID)
	if err != nil {
		appErr, ok := err.(appErrors.AppError)
		if ok && appErr.Code == appErrors.ErrCodeBookNotFound {
			return false, BookNotFound(bookID)
		}
		return false, DatabaseError(err)
	}

	// 暂时返回false，领域层应该实现真正的检查方法
	return false, nil
}
